#include "config.h" //通用配置头文件
#include "isr.h"

/*************  配置常量定义    **************/
// ADC 质量档位阈值（基于采样率）
#define FREQ_THRESHOLD_128X 145 // 128次平均最大支持频率
#define FREQ_THRESHOLD_64X 289	// 64次平均最大支持频率
#define FREQ_THRESHOLD_32X 579	// 32次平均最大支持频率
// 频率范围限制
#define MIN_TRANSFER_FREQ 1		  // 最小发送频率
#define MAX_TRANSFER_FREQ 1000	  // 最大发送频率
#define DEFAULT_TRANSFER_FREQ 100 // 默认发送频率

/*************  本地变量声明    **************/
volatile sensor_t sensor_data;			   // 传感器数据结构体变量
volatile config_t config_buf;			   // 配置持久化变量
volatile uint32_t config_read_success = 1; // 配置读取成功标志
/* K1K2按键事件标记 */
volatile uint32_t keyPressEvent[2] = {0};
volatile uint16_t gTransferFrequency = DEFAULT_TRANSFER_FREQ; // 传输频率，单位Hz
static uint32_t last_transfer_tick = 0;						  // 上次发送时间戳
/*************  本地函数声明    **************/
void sensor_setThreshold(void);
void sensor_calErr(void);

static inline void uart_send_response(const char *str)
{
	while (*str)
	{
		DL_UART_transmitData(UART_0_INST, *str++);
		while (DL_UART_isBusy(UART_0_INST))
			;
	}
}
int main(void)
{
	System_init(); // 天才第一步，使用SysConfig配置文件进行初始化。
	DL_WWDT_restart(WWDT0_INST);
#ifdef DEBUG // 调试模式下，检查GPIO是否复位和上电
#include <assert.h>
	assert(DL_GPIO_isReset(LED_PORT));
	assert(DL_GPIO_isPowerEnabled(LED_PORT));
#endif
	set_systick_ms(1);			 // 设置SysTick中断周期为1ms
	delay_ticks(10);			 // 延时10ms，等待系统稳定
	DL_WWDT_restart(WWDT0_INST); // 喂狗

	uart_init_frame(); // 初始化UART传输帧

	NVIC_EnableIRQ(UART_0_INST_INT_IRQN);  // 使能UART和定时器中断
	NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); // 使能定时器中断1ms用于按键扫描和显示刷新
	NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN); // 使能ADC中断
	NVIC_EnableIRQ(ADC12_1_INST_INT_IRQN); // 使能ADC中断
	// 启动ADC转换
	DL_ADC12_enableConversions(ADC12_0_INST);
	DL_ADC12_enableConversions(ADC12_1_INST);
	DL_ADC12_startConversion(ADC12_0_INST);
	DL_ADC12_startConversion(ADC12_1_INST);
	// 配置UART DMA传输
	DL_DMA_setSrcAddr(DMA, DMA_CH1_CHAN_ID, (uint32_t)&gTransferBuffer);
	DL_DMA_setDestAddr(DMA, DMA_CH1_CHAN_ID, (uint32_t)(&UART_0_INST->TXDATA));
	DL_DMA_setTransferSize(
		DMA, DMA_CH1_CHAN_ID, sizeof(gTransferBuffer) / sizeof(gTransferBuffer.bytes[0]));
	DL_DMA_enableChannel(DMA, DMA_CH1_CHAN_ID);
	// 配置UART DMA接收
	DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)(&UART_0_INST->RXDATA));
	DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gReceiveBuffer);
	DL_DMA_setTransferSize(
		DMA, DMA_CH0_CHAN_ID, sizeof(gReceiveBuffer) / sizeof(gReceiveBuffer.bytes[0]));
	DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
	// 读取持久化配置
	config_read_success = NVM_Param_Init((uint32_t *)&config_buf); // 初始化EEPROM模拟
	if (config_read_success == 0)
	{
		for (size_t i = 0; i < 16; i++)
		{
			sensor_data.threadhold[i] = config_buf.param.threadhold[i]; // 读取持久化阈值
			sensor_data.max[i] = config_buf.param.max[i];				// 读取持久化最大值
			sensor_data.min[i] = config_buf.param.min[i];				// 读取持久化最小值
		}
		gTransferFrequency = (config_buf.param.frequency > 0 && config_buf.param.frequency <= MAX_TRANSFER_FREQ)
								 ? config_buf.param.frequency
								 : DEFAULT_TRANSFER_FREQ; // 读取持久化频率
	}
	// 主循环
	while (1)
	{
		DL_WWDT_restart(WWDT0_INST); // 喂狗
		// 处理按键事件
		if (keyPressEvent[0] == 1) // 校正阈值按键事件（K1按键）
		{
			keyPressEvent[0] = 0;
			sensor_setThreshold();
		}
		// 处理UART接收指令
		if (gUartDMARXdone) // 接收到新指令
		{
			gUartDMARXdone = false;
			// 处理接收到的数据
			if (gReceiveBuffer.header[0] == 'E' &&
				gReceiveBuffer.header[1] == 'S' &&
				gReceiveBuffer.header[2] == 'D' &&
				gReceiveBuffer.bytes[3] == '=') // 指令格式"ESD=XXXX"
			{									// 校验指令格式
				if (gReceiveBuffer.bytes[4] >= '0' && gReceiveBuffer.bytes[4] <= '9' &&
					gReceiveBuffer.bytes[5] >= '0' && gReceiveBuffer.bytes[5] <= '9' &&
					gReceiveBuffer.bytes[6] >= '0' && gReceiveBuffer.bytes[6] <= '9' &&
					gReceiveBuffer.bytes[7] >= '0' && gReceiveBuffer.bytes[7] <= '9') // 频率范围0000-9999Hz
				{																	  // 校验频率格式
					uint16_t freq = (gReceiveBuffer.bytes[7] - '0') +
									(gReceiveBuffer.bytes[6] - '0') * 10 +
									(gReceiveBuffer.bytes[5] - '0') * 100 +
									(gReceiveBuffer.bytes[4] - '0') * 1000;		// 计算频率值
					if (freq >= MIN_TRANSFER_FREQ && freq <= MAX_TRANSFER_FREQ) // 限制频率范围
					{															// 频率有效，应用新频率
						gTransferFrequency = freq;

						// 根据新频率分段更新ADC平均值滤波配置
						// 必须先停止ADC转换，修改配置后重新启动
						NVIC_DisableIRQ(ADC12_0_INST_INT_IRQN);
						NVIC_DisableIRQ(ADC12_1_INST_INT_IRQN);
						// 停止ADC转换
						DL_ADC12_stopConversion(ADC12_0_INST);
						DL_ADC12_stopConversion(ADC12_1_INST);
						// 根据频率设置硬件平均值滤波档位
						if (gTransferFrequency <= FREQ_THRESHOLD_128X)
						{
							DL_ADC12_configHwAverage(ADC12_0_INST, DL_ADC12_HW_AVG_NUM_ACC_128, DL_ADC12_HW_AVG_DEN_DIV_BY_128);
							DL_ADC12_configHwAverage(ADC12_1_INST, DL_ADC12_HW_AVG_NUM_ACC_128, DL_ADC12_HW_AVG_DEN_DIV_BY_128);
						}
						else if (gTransferFrequency <= FREQ_THRESHOLD_64X)
						{
							DL_ADC12_configHwAverage(ADC12_0_INST, DL_ADC12_HW_AVG_NUM_ACC_64, DL_ADC12_HW_AVG_DEN_DIV_BY_64);
							DL_ADC12_configHwAverage(ADC12_1_INST, DL_ADC12_HW_AVG_NUM_ACC_64, DL_ADC12_HW_AVG_DEN_DIV_BY_64);
						}
						else if (gTransferFrequency <= FREQ_THRESHOLD_32X)
						{
							DL_ADC12_configHwAverage(ADC12_0_INST, DL_ADC12_HW_AVG_NUM_ACC_32, DL_ADC12_HW_AVG_DEN_DIV_BY_32);
							DL_ADC12_configHwAverage(ADC12_1_INST, DL_ADC12_HW_AVG_NUM_ACC_32, DL_ADC12_HW_AVG_DEN_DIV_BY_32);
						}
						else
						{
							DL_ADC12_configHwAverage(ADC12_0_INST, DL_ADC12_HW_AVG_NUM_ACC_16, DL_ADC12_HW_AVG_DEN_DIV_BY_16);
							DL_ADC12_configHwAverage(ADC12_1_INST, DL_ADC12_HW_AVG_NUM_ACC_16, DL_ADC12_HW_AVG_DEN_DIV_BY_16);
						}
						// 重新启动ADC转换
						DL_ADC12_startConversion(ADC12_0_INST);
						DL_ADC12_startConversion(ADC12_1_INST);
						// 重新使能 ADC 中断
						NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
						NVIC_EnableIRQ(ADC12_1_INST_INT_IRQN);
						// 频率有效，发送确认响应
						uart_send_response("OK\n");
						config_buf.param.frequency = gTransferFrequency; // 保存频率到持久化变量
						DL_WWDT_restart(WWDT0_INST);
						NVM_Param_Write((uint32_t *)&config_buf); // 持久化存储
						DL_WWDT_restart(WWDT0_INST);
					}
					else
					{
						// 频率无效，发送错误响应
						uart_send_response("E1\n");
					}
				}
				else
				{
					// 频率格式错误，发送错误响应
					uart_send_response("E2\n");
				}
			}
			else
			{
				// 指令格式错误，发送错误响应
				uart_send_response("E3\n");
			}
			// 清空FIFO残留数据
			while (DL_UART_isRXFIFOEmpty(UART_0_INST) == false)
			{
				DL_UART_receiveData(UART_0_INST);
			}
			// 重置DMA接收通道（从头开始）
			DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)(&UART_0_INST->RXDATA));
			DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gReceiveBuffer);
			DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, sizeof(gReceiveBuffer));
			DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID); // 重新启用DMA接收
			// 重新启用 TX DMA 通道，确保下次主循环可以正常发送传感器数据
			// 原因：
			// 1. TX DMA 可能在处理指令期间完成并被中断关闭
			// 2. 指令回执使用阻塞式 UART 立即发送（不通过 DMA 排队）
			// 3. 需要确保 TX DMA 状态与 gUartDMATXdone 标志一致
			// 4. 避免主循环误判 TX DMA 状态导致发送失败
			DL_DMA_enableChannel(DMA, DMA_CH1_CHAN_ID); // 重新启用DMA发送
		}
		// 处理传感器数据
		if (sensor_data.data_ready[0] && sensor_data.data_ready[1])
		{ // 数据准备就绪
			NVIC_DisableIRQ(ADC12_0_INST_INT_IRQN);
			NVIC_DisableIRQ(ADC12_1_INST_INT_IRQN);
			sensor_data.data_ready[0] = false;
			sensor_data.data_ready[1] = false;
			// 获取数据快照
			uint16_t raw_snapshot[16];
			memcpy(raw_snapshot, (void *)sensor_data.raw, sizeof(raw_snapshot));
			NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
			NVIC_EnableIRQ(ADC12_1_INST_INT_IRQN);
			// 计算阳性状态
			for (size_t i = 0; i < 16; i++)
			{
				sensor_data.positive[i] = raw_snapshot[i] > sensor_data.threadhold[i] ? 1 : 0;
			}
			// 计算边缘误差
			sensor_calErr();
			// 发送频率控制：检查是否满足发送间隔
			// 防止除零：gTransferFrequency 必须 >= 1
			uint32_t safe_freq = (gTransferFrequency > 0) ? gTransferFrequency : 100; // 默认100Hz
			uint32_t transfer_interval_ms = 1000 / safe_freq;						  // 计算发送间隔（毫秒）
			// 读取系统时间戳（注意：非严格原子操作）
			uint32_t current_tick = msTicks;
			// 汇编实现:
			//   LDR r0,[pc,#292]   ; 加载 &msTicks
			//   LDR r4,[r0,#0x00]  ; 读取 msTicks 值
			// 中断窗口: ~2时钟周期 (约 62ns @ 32MHz)
			// 影响评估: 最坏情况时间戳快1ms，对于毫秒级发送间隔可忽略
			// 设计决策: 性能优先，不添加中断保护
			if (gUartDMATXdone && (current_tick - last_transfer_tick >= transfer_interval_ms)) // 上次DMA发送完成且满足发送间隔
			{
				last_transfer_tick = current_tick; // 更新发送时间戳
				NVIC_DisableIRQ(UART_0_INST_INT_IRQN);
				gUartDMATXdone = false;
				gTransferBuffer.err = sensor_data.err; // 误差值
				// 构建阳性位图：16个传感器状态压缩到2字节（字节内位反向）
				// data[0]: sensor[0-7] 反向映射到 bit7-0
				// data[1]: sensor[8-15] 反向映射到 bit7-0
				uint8_t bitmap_low = 0;
				uint8_t bitmap_high = 0;
				for (size_t i = 0; i < 8; i++)
				{
					if (sensor_data.positive[i])
						bitmap_low |= (1 << i);
					if (sensor_data.positive[i + 8])
						bitmap_high |= (1 << i);
				}
				gTransferBuffer.data[0] = bitmap_high;
				gTransferBuffer.data[1] = bitmap_low;
				// 计算校验和：err + data[0] + data[1]
				uint8_t sum = (uint8_t)sensor_data.err + gTransferBuffer.data[0] + gTransferBuffer.data[1];
				gTransferBuffer.checksum = sum;
				// 启动DMA发送
				DL_DMA_enableChannel(DMA, DMA_CH1_CHAN_ID);
				NVIC_EnableIRQ(UART_0_INST_INT_IRQN);
			}
			// 渲染LED指示灯
			for (size_t i = 0; i < 16; i++)
			{
				LED4x4_SetNumber(i, sensor_data.positive[i]);
			}
			DL_WWDT_restart(WWDT0_INST);
		}
	}
	return 0;
}

void sensor_setThreshold(void)
{
	delay_ticks(10);
	LED4x4_SetAllPixels();
	// 等待数据准备就绪
	if (sensor_data.data_ready[0] && sensor_data.data_ready[1])
	{
		// 获取当前数据快照，重置最大值和最小值
		NVIC_DisableIRQ(ADC12_0_INST_INT_IRQN);
		NVIC_DisableIRQ(ADC12_1_INST_INT_IRQN);
		sensor_data.data_ready[0] = false;
		sensor_data.data_ready[1] = false;
		// 获取数据快照
		uint16_t raw_snapshot[16];
		memcpy(raw_snapshot, (void *)sensor_data.raw, sizeof(raw_snapshot));
		NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
		NVIC_EnableIRQ(ADC12_1_INST_INT_IRQN);
		// 更新最大值和最小值
		memcpy((void *)sensor_data.max, (void *)raw_snapshot, 32); // 重置最大值为当前值
		memcpy((void *)sensor_data.min, (void *)raw_snapshot, 32); // 重置最小值为当前值
	}
	// 持续监测数据，更新最大值和最小值，直到再次按键被检测
	while (keyPressEvent[0] == 0)
	{
		// 喂狗
		DL_WWDT_restart(WWDT0_INST);
		if (sensor_data.data_ready[0] && sensor_data.data_ready[1]) // 等待数据准备就绪
		{
			// 获取数据快照，更新最大值和最小值
			NVIC_DisableIRQ(ADC12_0_INST_INT_IRQN);
			NVIC_DisableIRQ(ADC12_1_INST_INT_IRQN);
			sensor_data.data_ready[0] = false;
			sensor_data.data_ready[1] = false;
			// 获取数据快照
			uint16_t raw_snapshot[16];
			memcpy(raw_snapshot, (void *)sensor_data.raw, sizeof(raw_snapshot));
			NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
			NVIC_EnableIRQ(ADC12_1_INST_INT_IRQN);
			// 更新最大值和最小值
			for (size_t i = 0; i < 16; i++)
			{
				if (raw_snapshot[i] > sensor_data.max[i])
				{
					sensor_data.max[i] = raw_snapshot[i];
				}
				if (raw_snapshot[i] < sensor_data.min[i])
				{
					sensor_data.min[i] = raw_snapshot[i];
				}
			}
		}
	}
	keyPressEvent[0] = 0;
	delay_ticks(10);
	for (size_t i = 0; i < 16; i++)
	{
		config_buf.param.max[i] = sensor_data.max[i];							   // 保存最大值到持久化变量
		config_buf.param.min[i] = sensor_data.min[i];							   // 保存最小值到持久化变量
		sensor_data.threadhold[i] = (sensor_data.max[i] + sensor_data.min[i]) / 2; // 计算并保存阈值
		config_buf.param.threadhold[i] = sensor_data.threadhold[i];				   // 保存阈值到持久化变量
	}
	DL_WWDT_restart(WWDT0_INST);
	NVM_Param_Write((uint32_t *)&config_buf); // 持久化存储
	DL_WWDT_restart(WWDT0_INST);
	delay_ticks(10);
	LED4x4_ClearAllPixels(); // 清除显示提示退出
}

void sensor_calErr(void)
{
	int8_t leftedge, rightedge, i;

	// 算法说明：
	// 1. 传感器阵列: [0][1][2]...[15] 共16个
	// 2. 黑线下方传感器值 > threshold (positive=1)
	// 3. 白线下方传感器值 < threshold (positive=0)
	// 4. 寻找黑白跳变沿，计算黑线中心相对阵列中心的偏差
	//
	// 示例:
	//   [0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0]
	//         ↑       ↑
	//     leftedge=2  rightedge=8
	//   黑线中心 = (2+8)/2 = 5
	//   阵列中心 = 7.5
	//   偏差 = 5 - 7.5 = -2.5 (左偏)
	//   实际计算: err = 15-2-8 = 5 (等价于偏差×2)

	leftedge = -1;
	for (i = 0; i < 15; i++)
	{
		if (sensor_data.positive[i + 1] != sensor_data.positive[i])
		{
			leftedge = i; // 记录左侧跳变点
			break;
		}
	}

	rightedge = -1;
	for (i = 15; i > 0; i--)
	{
		if (sensor_data.positive[i - 1] != sensor_data.positive[i])
		{
			rightedge = i; // 记录右侧跳变点
			break;
		}
	}

	// 异常情况：
	// - leftedge=-1 或 rightedge=-1: 未找到跳变（全黑/全白）
	// - leftedge >= rightedge: 跳变顺序异常
	if (leftedge == -1 || rightedge == -1 || leftedge >= rightedge)
	{
		sensor_data.err = 0; // 输出0，上位机判断为丢线
		return;
	}

	// 计算偏差: 15 - leftedge - rightedge
	// = (15 - leftedge - rightedge)
	// = 阵列宽度 - 左边界 - 右边界
	// 正值表示黑线偏右，负值表示偏左
	sensor_data.err = 15 - leftedge - rightedge;

	// 限幅到 [-15, 15]
	if (sensor_data.err > 15)
		sensor_data.err = 15;
	if (sensor_data.err < -15)
		sensor_data.err = -15;
}
